package com.qili.core.quartz.CustomQuartz;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.qili.entity.supervisor.SupervisorFile;
import com.qili.entity.supervisor.dto.SupervisorFileDTO;
import com.qili.service.ela.ElasticSerachService;
import com.qili.service.supervisor.SupervisorFileService;
import com.qili.util.StringUtil;
import lombok.extern.java.Log;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhaoyongke
 * @date 2022/5/14
 * @description
 */
@Log
public class SearchFileMysqlToEs implements Job {

    @Autowired
    ElasticSerachService elasticSerachService;


    @Autowired
    SupervisorFileService supervisorFileService;

    @Autowired
    RestHighLevelClient restHighLevelClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.info("同步es任务启动：启动任务=======================");
        run();
        log.info("同步es任务启动：下次执行时间=====" +
                new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
                        .format(context.getNextFireTime()) + "==============");
    }

    public void run() {
        //从file到es中国过渡
        log.info("SearchFileMysqlToEsJob=======开始==================================");
        String lockkey = "SearchFileMysqlToEsJob_key";
        String uuId = IdUtil.simpleUUID();
        try {
            lock(lockkey, uuId);
            saveUpdateFileToEs();
        } catch (Exception e) {
            log.info("SearchFileMysqlToEs=======出现异常了==================================");
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        } finally {
            log.info("SearchFileMysqlToEs=======释放锁==================================");
            unlock(lockkey, uuId);
        }
    }

    public void saveUpdateFileToEs() {

        log.info("同步es开始执行=======================");
        SupervisorFileDTO fileDTO = new SupervisorFileDTO();
        List<SupervisorFileDTO> supervisorFileDTOS = supervisorFileService.querySerachFileList(fileDTO);
        if (!CollectionUtils.isEmpty(supervisorFileDTOS)) {
            log.info("查询到的条数为=======================" + supervisorFileDTOS.size());
        }
        for (int i = 0; i < supervisorFileDTOS.size(); i++) {
            SupervisorFileDTO supervisorFileDTO = supervisorFileDTOS.get(i);
            saveOrUpdateElacSearchData(supervisorFileDTO, "");
        }
        log.info("同步es执行结束=======================");

    }

    public void saveOrUpdateElacSearchData(SupervisorFileDTO file, String content) {
        try {
            BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
            QueryBuilder queryBuilder = elasticSerachService.queryId(file.getId());
            boolBuilder.must(queryBuilder);
            SearchResponse searchResponse = elasticSerachService.searchMessage(boolBuilder, "", "", "");
            TotalHits totalHits = searchResponse.getHits().getTotalHits();
            Long total = totalHits.value;
            if (total > 0) {
                log.info("同步es执行结束=======================");
                SearchHit[] hits = searchResponse.getHits().getHits();
                Map<String, Object> sourceAsMap = hits[0].getSourceAsMap();
                SupervisorFileDTO fileupdate = JSON.parseObject(JSON.toJSONString(sourceAsMap), SupervisorFileDTO.class);
                //更新操作
                UpdateRequest updateRequest = new UpdateRequest("swordaa", file.getId());
                Map<String, Object> jsonMap = new HashMap<>();
               jsonMap.put("content",content);
                jsonMap.put("fileName", file.getFileName());
                jsonMap.put("searchKey", file.getSearchKey());
                jsonMap.put("id", file.getId());
                // 点赞人
                jsonMap.put("giveUser", file.getGiveUser());
                // 点赞数量
                jsonMap.put("dznum", file.getDznum());
                jsonMap.put("type", file.getType());
                jsonMap.put("createBy", file.getCreateBy());
                jsonMap.put("createUsername", file.getCreateUsername());
                jsonMap.put("url", file.getUrl());
                jsonMap.put("projectId", file.getProjectId());
                jsonMap.put("days", file.getDays());
                jsonMap.put("hotnum", file.getHotnum());
                jsonMap.put("remark", file.getRemark());
                jsonMap.put("createDate", file.getCreateDateStr());
                // 查询角色
                jsonMap.put("examineUser", file.getExamineUser());
                updateRequest.doc(jsonMap);
                UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
                log.info("更新es一条数据成功===========" + update.status() + "============");
            } else {
                // 保存 到elastaicsearch 中  2021 1006 增加
                IndexRequest indexRequest = new IndexRequest("swordaa");
                Map<String, Object> jsonMap = new HashMap<>();
                indexRequest.id(file.getId());
                jsonMap.put("id", file.getId());
                jsonMap.put("content", "");
                jsonMap.put("fileName", file.getFileName());
                if (StringUtil.isBlank(file.getSearchKey())) {
                    jsonMap.put("searchKey", "");
                } else {
                    jsonMap.put("searchKey", file.getSearchKey());
                }
                if (StringUtil.isBlank(file.getGiveUser())) {
                    jsonMap.put("giveUser", "");
                } else {
                    jsonMap.put("giveUser", file.getGiveUser());
                }

                // 点赞人

                // 点赞数量
                jsonMap.put("dznum", file.getDznum());
                jsonMap.put("type", file.getType());
                jsonMap.put("createBy", file.getCreateBy());
                jsonMap.put("createUsername", file.getCreateUsername());
                jsonMap.put("url", file.getUrl());
                jsonMap.put("projectId", file.getProjectId());
                jsonMap.put("days", file.getDays());
                jsonMap.put("hotnum", file.getHotnum());
                jsonMap.put("remark", file.getRemark());
                jsonMap.put("createDate", file.getCreateDateStr());
                // 查询角色
                if (StringUtil.isBlank(file.getExamineUser())) {
                    jsonMap.put("examineUser", "");
                } else {
                    jsonMap.put("examineUser", file.getExamineUser());
                }
                System.out.println(file.getExamineUser() + "角色=====================");
                indexRequest.source(jsonMap);
                IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
                if (index.getResult().name().equalsIgnoreCase("created")) {
                    log.info("插入es一条数据成功=======================");
                } else {
                    log.info("插入es一条数据失败=======================");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public void lock(String key, String uuId) {
        for (; ; ) {
            boolean r = stringRedisTemplate.opsForValue().setIfAbsent(key, uuId);
            stringRedisTemplate.expire(key, 600, TimeUnit.SECONDS);

            if (r) {
                return;
            } else {
                throw new RuntimeException("已经存在的执行程序...");
            }
        }
    }

    public void unlock(String key, String uuId) {
        if (uuId.equals(stringRedisTemplate.opsForValue().get(key))) {
            stringRedisTemplate.delete(key);
        }
    }
}
